/******************************************************
* Team WB
* Brett Cate, William Kim
* 
* ALU ADT Header
*******************************************************/


#ifndef SC2_H
#include "sc2.h"
#endif
#ifndef REGISTER16_H
#include "register16.h"
#endif

#ifndef ALU_H
#define ALU_H

// Register Numbers
#define REG_A		0
#define	REG_B		1
#define REG_R		2
#define REG_R2		3

typedef struct {
	RegisterPtr reg_A, reg_B, reg_R, reg_R2;
	RegisterPtr status_word_ptr;
} ALU;

typedef ALU* ALUPtr;

/*
Creates an ALU, initializes registers, and returns a pointer to the ALU.

parameter (*the_status_word): Pointer to the status word register for the ALU.
parameter (*the_error): Pointer to the int value of the error code.

return value: Pointer to the ALU.
*/
ALUPtr alu_new(RegisterPtr the_status_word_ptr, int* the_error);


/*
Sets the ALU's status word reference to the given Register pointer and returns
the error code for this function.

parameter (the_ALU): Pointer to the ALU whose status word reference is set.
parameter (*the_status_word): Pointer to the new status word register for the ALU.

return value: An int containing the value of the error code for this function.
*/
int alu_setSWReference(ALUPtr the_ALU, RegisterPtr the_status_word_ptr);

/*
Clears the given ALU's status word flags.

parameter (the_ALU): Pointer to the ALU whose status word flags are 
cleared (set to 0000).

return value: An int containing the value of the error code for this function.
*/
int alu_clearFlags(ALUPtr the_ALU);

/*
Sets the status word to the lower 4 bits of the given ushort and returns the error
code for this function.

parameter (the_ALU): Pointer to the ALU whose status word flags are set.
parameter (the_bitmask): The ushort bitmask used to set the status word, using the lowest
4 bits of the ushort.

return value: An int containing the value of the error code for this function.
*/
int alu_setFlags(ALUPtr the_ALU, ushort the_bitmask);

/*
Sets the indicated register in the ALU to the given value and returns the 
error code for this function.

parameter (the_ALU): Pointer to the ALU whose register is set.
parameter (the_register_number): The register number whose value is set.
parameter (the_value): The Register (a ushort) value to set the indicated register to.

return value: An int containing the error code for this function.
*/
int alu_setRegister(ALUPtr the_ALU, int the_register_number, Register the_value);

/*
Returns the value of the indicated register, either R (0) or R2 (1).

parameter (the_ALU): Pointer to the ALU whos register value is returned.
parameter (the_register_number): The register number of the register to return.
Either 0 for register R or 1 for register R2.
parameter (*the_error): Pointer to an int containing the value of the error
code for this function.

return value: A Register (ushort) containing the value of the indicated ALU register.
*/
Register alu_getResult(ALUPtr the_ALU, int the_register_number, int* the_error);

/*
Function for determining which ALU operation to perform.

parameter (the_ALU): Pointer to the ALU which executes the operation.
parameter (the_op): The operation to perform.

return value: An int containing the error code for this function.
*/
int alu_op(ALUPtr the_ALU, int the_op);

/*
Calculates value of registers A + B and puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_ADD(ALUPtr the_ALU);

/*
Calculates value of registers A - B and puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_SUB(ALUPtr the_ALU);

/*
Calculates value of registers A * B and puts the resulting high order
word in the R2 register, and the low order word in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_MUL(ALUPtr the_ALU);

/*
Calculates value of registers A / B and puts the quotient 
in the R register, and the remainder in the R2 register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_DIV(ALUPtr the_ALU);

/*
Calculates bitwise AND of registers A and B and puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_AND(ALUPtr the_ALU);

/*
Calculates bitwise OR of registers A and B and puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_OR(ALUPtr the_ALU);

/*
Calculates bitwise XOR (exclusive OR) of registers A and B and 
puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_XOR(ALUPtr the_ALU);

/*
Calculates bitwise NOT of register A and puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_NOT(ALUPtr the_ALU);

/*
Shifts the value of register A one bit to the left and
puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_SHL(ALUPtr the_ALU);

/*
Shifts the value of register A one bit to the right and
puts the result in the R register.

parameter (the_ALU): Pointer to the ALU which executes the operation.

return value: An int containing the error code for this function.
*/
int alu_SHR(ALUPtr the_ALU);

/*
Determines if a value resulted in a carry bit.

parameter (the_result): The resulting value as 32 bits.

return value: TRUE if the 16th bit has a 1 in it; FALSE otherwise.
*/
int alu_isCarry(int the_result);

#endif

/* End Program */
